---------------------------------------------------------------------------------------------------- -- Walkers --------------------------------------------------------------------------------------------------------------------- class "evaluator_need_walker" (property_evaluator) function evaluator_need_walker:__init(storage, name) super(nil, name) self.st = storage end function evaluator_need_walker:evaluate() return xr_logic.is_active(self.object, self.st) end local assoc_tbl = { idle = {director = {"wait"}}, harmonica = {director = {"play_harmonica"}}, guitar = {director = {"play_guitar"}}, story = {director = {"wait"}}, } ---------------------------------------------------------------------------------------------------------------------- class "action_walker_activity" (action_base) function action_walker_activity:__init (npc, action_name, storage) super(nil, action_name) self.st = storage self.move_mgr = db.storage[npc:id()].move_mgr self.st.description = "walker_camp" self.avail_actions = xr_animpoint_predicates.associations[self.st.description] self.st.approved_actions = {} for k,v in pairs(self.avail_actions) do -- Убираем те действия, которые не подходят по прекондишну if v.predicate(npc:id())==true then self.st.approved_actions[#self.st.approved_actions+1] = v end end end function action_walker_activity:initialize() action_base.initialize(self) --utils_data.debug_write(strformat("action_walker_activity:initialize %s",self.object:name())) self.object:set_desired_position() self.object:set_desired_direction() self:reset_scheme(nil, self.object) end function action_walker_activity:activate_scheme(loading, npc) self.st.signals = {} self:reset_scheme(loading, npc) end function action_walker_activity:reset_scheme(loading, npc) if self.st.path_walk_info == nil then self.st.path_walk_info = utils_obj.path_parse_waypoints(self.st.path_walk) end if self.st.path_look_info == nil then self.st.path_look_info = utils_obj.path_parse_waypoints(self.st.path_look) end if (self.move_mgr) then self.move_mgr:reset(self.st.path_walk, self.st.path_walk_info, self.st.path_look, self.st.path_look_info, self.st.team, self.st.suggested_state) end end function action_walker_activity:execute() action_base.execute(self) --utils_data.debug_write(strformat("action_walker_activity:execute %s",self.object:name())) self.move_mgr:update() -- Определяем, в каком мы кемпе. local state = state_mgr.get_state(self.object) local camp = sr_camp.get_current_camp(self.object:position()) if (camp) then if (self.st.use_camp == true and state ~= "sleep" and state ~= "sleep_sit") then self.camp = camp self.camp:register_npc(self.object:id()) self.in_camp = true elseif (self.st.use_camp == false or state == "sleep" or state == "sleep_sit") then if self.in_camp == true then self.camp:unregister_npc(self.object:id()) self.in_camp = nil self.camp = nil end end elseif (self.in_camp == true and self.camp ~= nil) then self.camp:unregister_npc(self.object:id()) self.in_camp = nil self.camp = nil end if (state == "sleep" or state == "sleep_sit") then return end if not self.in_camp and self.st.sound_idle ~= nil then xr_sound.set_sound_play(self.object:id(), self.st.sound_idle) end end function action_walker_activity:update() --printf("update") if self.camp == nil then return end local camp_action, is_director = self.camp:get_camp_action(self.object:id()) --printf("camp_action %s, %s", camp_action, tostring(is_director)) if not is_director then return end local tbl = assoc_tbl[camp_action].director local anm = tbl[math.random(#tbl)] state_mgr.set_state(self.object, anm) end function action_walker_activity:finalize() self.move_mgr:finalize() if self.in_camp == true then self.camp:unregister_npc(self.object:id()) self.in_camp = nil end action_base.finalize(self) end --' Возвращает достиг ли персонаж точки начала работы схемы function action_walker_activity:position_riched() return self.move_mgr:arrived_to_first_waypoint() end function action_walker_activity:net_destroy(npc) if self.in_camp == true then self.camp:unregister_npc(npc:id()) self.in_camp = nil end end ---------------------------------------------------------------------------------------------------------------------- --walker binder ---------------------------------------------------------------------------------------------------------------------- function add_to_binder(npc, ini, scheme, section, storage) if not npc then return end --printf("DEBUG: add_to_binder: scheme='%s', section='%s'", scheme, section) local operators = {} local properties = {} local manager = npc:motivation_action_manager() if not manager then return end properties["event"] = xr_evaluators_id.reaction properties["need_walker"] = xr_evaluators_id.zmey_walker_base + 1 properties["state_mgr_logic_active"] = xr_evaluators_id.state_mgr + 4 operators["action_walker"] = xr_actions_id.zmey_walker_base + 1 -- -- evaluators local evaluator = this.evaluator_need_walker(storage, "walker_need") -- callstack() local new_action = this.action_walker_activity(npc, "action_walker_activity", storage) if not evaluator or not new_action then return end manager:add_evaluator(properties["need_walker"], evaluator) new_action:add_precondition(world_property(stalker_ids.property_alive, true)) new_action:add_precondition(world_property(stalker_ids.property_danger,false)) new_action:add_precondition(world_property(stalker_ids.property_enemy, false)) --new_action:add_precondition(world_property(xr_danger.evaid,false)) new_action:add_precondition(world_property(properties["need_walker"], true)) modules.add_common_precondition(scheme,new_action) new_action:add_effect(world_property(properties["need_walker"], false)) new_action:add_effect (world_property(properties["state_mgr_logic_active"], false)) manager:add_action(operators["action_walker"], new_action) -- Зарегистрировать все actions, в которых должен быть вызван метод reset_scheme при изменении настроек схемы: xr_logic.subscribe_action_for_events(npc, storage, new_action) --printf("ACTION_ALIFE_ID(xr_walker.add_to_binder): " .. tostring(xr_actions_id.alife)) new_action = manager:action(xr_actions_id.alife) if new_action then new_action:add_precondition(world_property(properties["need_walker"], false)) end end -- Включение схемы -- -- enabled - включена ли схема -- path_walk - основной путь, по которому ходит охранник -- path_look [опционально] - путь, куда смотрит охранник -- team [опционально] - команда для синхронизации -- function set_scheme(npc, ini, scheme, section, gulag_name) --printf("DEBUG: set_scheme: scheme='%s', section='%s', gulag_name='%s'", scheme, section, tostring(gulag_name)) local st = xr_logic.assign_storage_and_bind(npc, ini, scheme, section) --printf("DEBUG: set_scheme: storage assigned") st.logic = xr_logic.cfg_get_switch_conditions(ini, section, npc) st.path_walk = utils_data.prefix_r_string(ini,section,"path_walk",gulag_name) if not level.patrol_path_exists(st.path_walk) then printe("!ERROR: There is no patrol path %s", st.path_walk) end st.path_look = utils_data.prefix_r_string(ini,section,"path_look",gulag_name) if st.path_walk == st.path_look then printe("!ERROR: You are trying to set 'path_look' equal to 'path_walk' in section [%s] for npc [%s]", section, npc:name()) end -- not sure if used anymore --st.team = utils_data.prefix_r_string(ini,section,"team",gulag_name) st.sound_idle= ini:r_string_ex(section,"sound_idle") st.use_camp = ini:r_bool_ex(section,"use_camp",false) st.suggested_state = {} st.suggested_state.standing = ini:r_string_ex(section,"def_state_standing") st.suggested_state.moving = ini:r_string_ex(section,"def_state_moving1") st.suggested_state.moving = ini:r_string_ex(section,"def_state_moving") or st.suggested_state.moving st.path_walk_info = nil -- Будут инициализированы в reset(), сейчас пути могут быть еще st.path_look_info = nil -- не загружены. end